package com.zn.web.controller;

import com.aliyun.oss.OSSClient;
import com.zn.entity.*;
import com.zn.service.*;
import com.zn.util.Constant;
import com.zn.util.DateUtils;
import com.zn.util.EnDecryptUtil;
import com.zn.util.OSSUtil;
import com.zn.vo.Message;
import com.zn.vo.PayMethodVo;
import com.zn.web.dto.CustomerWithdrawDto;
import com.zn.web.dto.OnLineRechargeDto;
import com.zn.web.dto.PayChannelDto;
import com.zn.web.dto.UnderLineRechargeDto;
import com.zn.web.vo.CustomerCapitalVo;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/payInfo")
public class PayController {
    private static final Logger LOGGER = LoggerFactory.getLogger(PayController.class);
    @Autowired
    private PayChannelService payChannelService;
    @Autowired
    private PayTypeService payTypeService;
    @Autowired
    private AppCustomerService appCustomerService;
    @Autowired
    private CustomerBankInfoService customerBankInfoService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private PayTimeLimitService payTimeLimitService;
    @Value("${oss.end.point}")
    private  String endPoint;
    @Value("${oss.access.key.id}")
    private  String accessKeyId;
    @Value("${oss.access.key.secret}")
    private  String accessKeySecret;
    @Value("${oss.bucket.name}")
    private  String bucketName;
    @Value("${oss.url}")
    private  String ossUrl;

    /**
     * 点击充值接口
     * @return
     */
    @RequestMapping(value = "/getPayList",method = RequestMethod.POST)
    public ResponseEntity<Message> getPayChannel(@RequestBody PayChannelDto payChannelDto) {
        try {
            if(StringUtils.isEmpty(payChannelDto.getCustomerId()) || isAllFieldNull(payChannelDto)){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            AppCustomer appCustomer=appCustomerService.selectByPrimaryKey(payChannelDto.getCustomerId());
            if(StringUtils.isBlank(appCustomer.getCustomerCapitalPassword())){
                //资金密码为空 设置资金密码
                return ResponseEntity.ok(Message.CAPITAL_PASSWORD_NULL);
            }
            /*List<CustomerBankInfo> customerBankInfoList=customerBankInfoService.selectByCustomerId(payChannelDto.getCustomerId());
            if(customerBankInfoList==null || customerBankInfoList.size()==0){
                //当前用户未绑卡
                return ResponseEntity.ok(Message.CUSTOMER_IS_NOT_AUTHENTICATION);
            }*/
            /**校验当前是否在允许时间内**/
            boolean payTimeLimitFlag=payTimeLimitService.checkLimitTime(1);
            if(!payTimeLimitFlag){
                return ResponseEntity.ok(Message.NOT_RECHARGE_TIME);
            }
            /**查询线上自动充值方式**/
            List<PayMethodVo> payMethodVoList= payChannelService.selectPayChannel(payChannelDto.getPayMethod());
            /**线下打款收款人信息**/
            List<OfflinePayment> offlinePaymentList=customerBankInfoService.getOfflinePaymentList();
            /**查询充值方式**/
            List<PayType> payTypes=payTypeService.selectPayType();
            /**获取快捷充值金额集合**/
            Set<String> amountSet=redisTemplate.opsForSet().members(Constant.QUICK_RECHARGE_AMOUNT_SET);
            /**如果查到没有 则初始化4条数据进去**/
            if(amountSet==null || amountSet.size()==0){
                amountSet=new LinkedHashSet<String>(){{
                    add("3000");
                    add("5000");
                    add("10000");
                    add("15000");
                }};
            }
            Map<String,Object> map=new HashMap<String,Object>();
            map.put("type",payTypes);
            map.put("channel",payMethodVoList);
            map.put("offlinePaymentList",offlinePaymentList);
            map.put("amountSet",amountSet);
            return ResponseEntity.ok(Message.successData(map));
        }catch (Exception e){
            LOGGER.error("getPayList..........", e);
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }

    /**
     * 进入提现接口 校验是否设置了资金密码
     * @return
     */
    @RequestMapping(value = "/clickWithdraw",method = RequestMethod.POST)
    public ResponseEntity<Message> clickWithdraw(@RequestBody PayChannelDto payChannelDto) {
        if(StringUtils.isBlank(payChannelDto.getCustomerId()) || StringUtils.isBlank(payChannelDto.getCustomerCapitalPassword())){
            ResponseEntity.ok(Message.ARGS_ERROR);
        }
        AppCustomer appCustomer=appCustomerService.selectByPrimaryKey(payChannelDto.getCustomerId());
        if(appCustomer==null){
            return ResponseEntity.ok(Message.CUSTOMER_NOT_EXIST);
        }

        try {
            boolean payTimeLimitFlag=payTimeLimitService.checkLimitTime(2);
            if(!payTimeLimitFlag){
                return ResponseEntity.ok(Message.NOT_WITHDRAW_TIME);
            }
            ResponseEntity<Message> responseEntity= payChannelService.clickWithdraw(payChannelDto);
            return responseEntity;
        }catch (Exception e){
            LOGGER.error("clickWithdraw....",e);
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }

    /**
     * 线下充值
     * @return
     */
    @RequestMapping(value = "/underLineRecharge",method = RequestMethod.POST)
    public ResponseEntity<Message> underLineRecharge(@RequestBody UnderLineRechargeDto underLineRechargeDto) {
        try {
            LOGGER.info("underLineRechargeDto:" + underLineRechargeDto.toString());
            //key：IDEMPOTENCY:underLineRecharge-customerId
            Object redisIdempotency=redisTemplate.opsForValue().get(Constant.IDEMPOTENCY_UNDERLINERECHARGE+underLineRechargeDto.getCustomerId());
            if(redisIdempotency!=null && underLineRechargeDto.getIdempotency().equals(redisIdempotency.toString())){
                LOGGER.info("underLineRechargeDto.getIdempotency():" + underLineRechargeDto.getIdempotency() + ",redisIdempotency.toString():" + (redisIdempotency == null ? "is null" : redisIdempotency.toString()));
                LOGGER.info("接口:underLineRecharge，时间：" + DateUtils.parseToDateTimeStr(new Date())+",拦截了用户的重复提交请求,参数为："+underLineRechargeDto.toString());
                //操作成功 处理幂等性问题
                return ResponseEntity.ok(Message.REQ_SUCCESS);
            }
            ResponseEntity<Message> responseEntity=payChannelService.underLineRecharge(underLineRechargeDto);
            LOGGER.info("responseEntity.......success");
            return responseEntity;
        }catch (Exception e){
            LOGGER.error("underLineRecharge..........",e);
            redisTemplate.delete(Constant.IDEMPOTENCY_UNDERLINERECHARGE + underLineRechargeDto.getCustomerId());
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }
    /**
     *
     * OSSUtil ossUtil=OSSUtil.getInstance(endPoint,accessKeyId,accessKeySecret,bucketName,ossUrl);
     //上传目录 代理商code/TransferVoucher
     String imgFolder = "TransferVoucher/"+DateUtils.formatDate(new Date());
     OSSClient ossClient = ossUtil.getOSSClient();
     String fileName = System.currentTimeMillis()+"-"+ DateUtils.getDate(new Date())+ "." + voucher.getOriginalFilename().substring(voucher.getOriginalFilename().lastIndexOf(".") + 1);
     //开始上传图片
     boolean uploadFlag = ossUtil.uploadInputStreamObject2OSS(ossClient, voucher.getInputStream(), fileName, imgFolder);
     if(!uploadFlag){
     //文件上传异常
     return ResponseEntity.ok(Message.UPLOAD_FILE_ERROR);
     }
     String filePath=ossUtil.getOssUrl() + "/" + imgFolder + "/" + fileName;
     *
     */

    /**
     * 线上充值
     * @return
     */
    @RequestMapping(value = "/onLineRecharge",method = RequestMethod.POST)
    public ResponseEntity<Message> onLineRecharge(@RequestBody OnLineRechargeDto onLineRechargeDto) {
        try {
            /**参数异常**/
            if(StringUtils.isBlank(onLineRechargeDto.getCustomerId()) || StringUtils.isBlank(onLineRechargeDto.getAccountName())
                    || onLineRechargeDto.getPayMethod()==null || onLineRechargeDto.getAccountId()==null ||
                    onLineRechargeDto.getRechargeAmount()==null){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            ResponseEntity<Message> responseEntity=payChannelService.onLineRecharge(onLineRechargeDto);
            return responseEntity;
        }catch (Exception e){
            LOGGER.error("onLineRecharge..........", e);
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }
    /**
     * 客户提现
     * @return
     */
    @RequestMapping(value = "/customerWithdraw",method = RequestMethod.POST)
    public ResponseEntity<Message> customerWithdraw(@RequestBody CustomerWithdrawDto customerWithdrawDto) {
        try {
            if(StringUtils.isBlank(customerWithdrawDto.getCustomerId()) || customerWithdrawDto.getWithdrawAmount()==null
                    || StringUtils.isBlank(customerWithdrawDto.getCustomerBankId()) || customerWithdrawDto.getWithdrawType()==null){
                ResponseEntity.ok(Message.ARGS_ERROR);
            }
            ResponseEntity responseEntity=payChannelService.customerWithdraw(customerWithdrawDto);
            return responseEntity;
        }catch (Exception e){
            LOGGER.error("customerWithdraw..........", e);
            return ResponseEntity.ok(Message.SYS_ERROR);
        }

    }

    /**
     * 查询用户资金历史记录
     * @param customerWithdrawDto
     * @return
     */
    @RequestMapping(value = "/customerWithdrawRecord",method = RequestMethod.POST)
    public ResponseEntity<Message> customerWithdrawRecord(@RequestBody CustomerWithdrawDto customerWithdrawDto) {
        try {
            if(StringUtils.isEmpty(customerWithdrawDto.getCustomerId())){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            /**处理来自H5的请求**/
            if(customerWithdrawDto.getIsH5()!=null){
                if(customerWithdrawDto.getStatus()!=null){
                    customerWithdrawDto.setStatusDescribe(customerWithdrawDto.convertStatus(customerWithdrawDto.getStatus()));
                }
                if(StringUtils.isNotBlank(customerWithdrawDto.getCreateTimeBegin())){
                    customerWithdrawDto.setCreateTimeBegin(customerWithdrawDto.getCreateTimeBegin() + " 00:00:00");
                }
                if(StringUtils.isNotBlank(customerWithdrawDto.getCreateTimeEnd())){
                    customerWithdrawDto.setCreateTimeEnd(customerWithdrawDto.getCreateTimeEnd()+" 23:59:59");
                }
                List<CustomerCapitalVo> list = payChannelService.getCustomerCapitalRecord(customerWithdrawDto);
                int count=payChannelService.getCustomerCapitalRecordCount(customerWithdrawDto);
                Map<String,Object> map=new HashMap<String,Object>();
                map.put("list",list);
                map.put("count", count);
                return ResponseEntity.ok(Message.successData(map));
            }
            List<CustomerCapitalVo> list = payChannelService.getCustomerCapitalRecord(customerWithdrawDto);
            return ResponseEntity.ok(Message.page(list));
        } catch (Exception e) {
            LOGGER.error("customerWithdrawRecord..........", e);
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }

    //判断该对象是否: 返回ture表示所有属性为null  返回false表示不是所有属性都是null
    public static boolean isAllFieldNull(Object obj) throws Exception{
        Class stuCla = (Class) obj.getClass();// 得到类对象
        Field[] fs = stuCla.getDeclaredFields();//得到属性集合
        boolean flag = true;
        for (Field f : fs) {//遍历属性
            f.setAccessible(true); // 设置属性是可以访问的(私有的也可以)
            Object val = f.get(obj);// 得到此属性的值
            if(val!=null) {//只要有1个属性不为空,那么就不是所有的属性值都为空
                flag = false;
                break;
            }
        }
        return flag;
    }

}